#include <stdio.h>

int f(int a, int b, int c)
{
	return a * b + c;
}

int main()
{
	printf("%d\n", f(1, 2, 3));	// 5
	return 0;
}

#if 0

调用方(caller)函数通过栈向被调用方(callee)函数传递参数。

/*
 * x86
 */

	
/*
 * x64
 */
	能够使用寄存器传递(前4个或前6个)参数。

	LEA 的效率比 ADD 的效率高，向寄存器赋值的速度也比MOV快。

	比较意外的是，原本位于寄存器的3个参数都被推送到了栈里。这种现象叫作"阴影空间/shadow space"。

	每个win64程序都可以(但非必须)把4个寄存器的值保存到阴影空间里。使用阴影空间有两个优点：
	1.通过栈传递参数，可避免浪费寄存器资源(有时可能会占用4个寄存器)。
	2.便于调试器在程序中断时找到函数参数。

	大型函数可能会把输入参数保存在阴影空间里，但是小型函数可能就不会使用阴影空间了。

	在使用阴影空间时，由调用方函数分配栈空间，由被调用方函数根据需要将寄存器参数转储到它们阴影空间中。

/*
 * gcc
 */
	阴影空间只是微软的概念，system V*nix里没有这种规范或约定。
	GCC只在在寄存器数量容纳不下所有参数的情况下，才会使用栈传递参数。


#endif

#if 0
/*
 * intel
 */
0000000000001149 <f>:
    1149:	f3 0f 1e fa          	endbr64 
    114d:	55                   	push   %rbp
    114e:	48 89 e5             	mov    %rsp,%rbp
    1151:	89 7d fc             	mov    %edi,-0x4(%rbp)  // 1
    1154:	89 75 f8             	mov    %esi,-0x8(%rbp)  // 2
    1157:	89 55 f4             	mov    %edx,-0xc(%rbp)  // 3
    115a:	8b 45 fc             	mov    -0x4(%rbp),%eax  // eax=a
    115d:	0f af 45 f8          	imul   -0x8(%rbp),%eax  // eax=a*b
    1161:	89 c2                	mov    %eax,%edx        // edx=eax
    1163:	8b 45 f4             	mov    -0xc(%rbp),%eax  // eax=c
    1166:	01 d0                	add    %edx,%eax        // eax=a*b+c
    1168:	5d                   	pop    %rbp
    1169:	c3                   	retq   

000000000000116a <main>:
    116a:	f3 0f 1e fa          	endbr64 
    116e:	55                   	push   %rbp
    116f:	48 89 e5             	mov    %rsp,%rbp
    1172:	ba 03 00 00 00       	mov    $0x3,%edx        // edx=3
    1177:	be 02 00 00 00       	mov    $0x2,%esi        // esi=2
    117c:	bf 01 00 00 00       	mov    $0x1,%edi        // edi=1
    1181:	e8 c3 ff ff ff       	callq  1149 <f>
    1186:	89 c6                	mov    %eax,%esi
    1188:	48 8d 3d 75 0e 00 00 	lea    0xe75(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    118f:	b8 00 00 00 00       	mov    $0x0,%eax
    1194:	e8 b7 fe ff ff       	callq  1050 <printf@plt>
    1199:	b8 00 00 00 00       	mov    $0x0,%eax
    119e:	5d                   	pop    %rbp
    119f:	c3                   	retq  

/*
 * arm
 */
000000000040055c <f>:
  40055c:	d10043ff 	sub	sp, sp, #0x10
  400560:	b9000fe0 	str	w0, [sp, #12]   // 1
  400564:	b9000be1 	str	w1, [sp, #8]    // 2
  400568:	b90007e2 	str	w2, [sp, #4]    // 3
  40056c:	b9400fe1 	ldr	w1, [sp, #12]   // w1=1
  400570:	b9400be0 	ldr	w0, [sp, #8]    // w0=2
  400574:	1b007c21 	mul	w1, w1, w0      // w1=1*2
  400578:	b94007e0 	ldr	w0, [sp, #4]    // w0=3
  40057c:	0b000020 	add	w0, w1, w0      // w0=1*2+3
  400580:	910043ff 	add	sp, sp, #0x10
  400584:	d65f03c0 	ret

0000000000400588 <main>:
  400588:	a9bf7bfd 	stp	x29, x30, [sp, #-16]!
  40058c:	910003fd 	mov	x29, sp
  400590:	52800062 	mov	w2, #0x3                   	// #3
  400594:	52800041 	mov	w1, #0x2                   	// #2
  400598:	52800020 	mov	w0, #0x1                   	// #1
  40059c:	97fffff0 	bl	40055c <f>
  4005a0:	2a0003e1 	mov	w1, w0
  4005a4:	90000000 	adrp	x0, 400000 <_init-0x3e8>
  4005a8:	9119c000 	add	x0, x0, #0x670
  4005ac:	97ffffa9 	bl	400450 <printf@plt>
  4005b0:	52800000 	mov	w0, #0x0                   	// #0
  4005b4:	a8c17bfd 	ldp	x29, x30, [sp], #16
  4005b8:	d65f03c0 	ret
  4005bc:	00000000 	.inst	0x00000000 ; undefined
#endif

